﻿// Copyright 2009 Mike Geise
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Falcon.Core.Services
{
	using System.Collections.Generic;
	using Falcon.Core.Domain;
	using Falcon.Core.Domain.Enums;
	using Falcon.Core.Domain.Repositories;
	using Falcon.Core.Domain.Services;
	using Falcon.Core.Domain.Values;

	public class UserPermissionService : IUserPermissionService
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="UserPermissionService"/> class.
		/// </summary>
		/// <param name="userPermissionRepository">The user permission repository.</param>
		public UserPermissionService(IUserPermissionRepository userPermissionRepository)
		{
			this.UserPermissionRepository = userPermissionRepository;
		}

		/// <summary>
		/// Gets or sets the user permission repository.
		/// </summary>
		/// <value>The user permission repository.</value>
		public IUserPermissionRepository UserPermissionRepository
		{
			get; 
			private set;
		}

		/// <summary>
		/// Gets the user permission by the specified specification.
		/// </summary>
		/// <param name="specification">The <see cref="UserPermissionSpecification"/>.</param>
		/// <returns></returns>
		public UserPermission GetBy(UserPermissionSpecification specification)
		{
			return this.UserPermissionRepository.GetBy(specification);
		}

		/// <summary>
		/// Gets the user permission by id.
		/// </summary>
		/// <param name="id">The id.</param>
		/// <returns></returns>
		public UserPermission GetById(int id)
		{
			return this.UserPermissionRepository.GetById(id);
		}

		/// <summary>
		/// Gets all the user permissions by the specified specification.
		/// </summary>
		/// <param name="specification">The <see cref="UserPermissionSpecification"/>.</param>
		/// <returns></returns>
		public IList<UserPermission> GetAll(UserPermissionSpecification specification)
		{
			return this.UserPermissionRepository.GetAll(specification);
		}

		/// <summary>
		/// Gets all the user permissions grouped by role using the specified specification.
		/// </summary>
		/// <param name="specification">The specification.</param>
		/// <returns></returns>
		public Dictionary<string, UserPermission> GetGrouped(UserPermissionSpecification specification)
		{
			var permissions = this.GetAll(specification);
			var keyed = new Dictionary<string, UserPermission>();

			foreach (var permission in permissions)
			{
				keyed.Add(permission.Role.Title, permission);
			}

			return keyed;
		}

		/// <summary>
		/// Creates the user permission.
		/// </summary>
		/// <returns></returns>
		public UserPermission Create()
		{
			return new UserPermission();
		}

		/// <summary>
		/// Inserts the user permission into the storage.
		/// </summary>
		/// <param name="permission">The <see cref="UserPermission"/>.</param>
		public void Insert(UserPermission permission)
		{
			this.UserPermissionRepository.Insert(permission);
		}

		/// <summary>
		/// Updates the user permission in the storage.
		/// </summary>
		/// <param name="permission">The <see cref="UserPermission"/>.</param>
		public void Update(UserPermission permission)
		{
			this.UserPermissionRepository.Update(permission);
		}

		/// <summary>
		/// Updates the user permission in the storage.
		/// </summary>
		/// <param name="user">The user.</param>
		/// <param name="values">The values.</param>
		public void Update(User user, UserPermissionUpdate[] values)
		{
			for (var i = 0; i < values.Length; i++)
			{
				var permission = this.GetBy(new UserPermissionSpecification
				{
					UserId = user.Id,
					RoleId = values[i].RoleId
				});

				if (values[i].Selected)
				{
					var action = 0;

					for (var k = 0; k < values[i].Permissions.Length; k++)
					{
						if (!values[i].Permissions[k].Selected)
						{
							continue;
						}

						action |= values[i].Permissions[k].Action;
					}

					if (permission == null)
					{
						permission = this.Create();

						permission.UserId = user.Id;
						permission.RoleId = values[i].RoleId;
						permission.Action = (UserPermissionActions)action;

						this.Insert(permission);
					}
					else
					{
						permission.Action = (UserPermissionActions)action;

						this.Update(permission);
					}
				}
				else
				{
					if (permission != null)
					{
						this.Delete(permission);
					}
				}
			}
		}

		/// <summary>
		/// Deletes the user permission in the storage.
		/// </summary>
		/// <param name="permission">The <see cref="UserPermission"/>.</param>
		public void Delete(UserPermission permission)
		{
			this.UserPermissionRepository.Delete(permission);
		}
	}
}